package com.fan.demo2;

import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.ShardingStrategyConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.StandardShardingStrategyConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableConfigurationProperties({ ShardingSphereConfigProperties.class })
public class ShardingSphereConfiguration {

	private static final Logger LOGGER = LoggerFactory.getLogger(ShardingSphereConfiguration.class);

	@Autowired
    ShardingSphereConfigProperties shardingSphereConfigProperties;

	/**
	 * 分片表规则配置
	 * 
	 * @return
	 */
	@Bean
	public List<TableRuleConfiguration> tableRuleConfigurations() {
		 List<String> logicTableList = shardingSphereConfigProperties.getLogicTable();
		 List<String> actualDataNodesList = shardingSphereConfigProperties.getActualDataNodes();
		 List<String> shardingColumnsList = shardingSphereConfigProperties.getShardingColumns();
		 List<String> shardingStrategysList = shardingSphereConfigProperties.getShardingStrategys();
//		 List<String> shardingAlgorithmsList = shardingSphereConfigProperties.getShardingAlgorithms();

		if (logicTableList.size() <= 0 || actualDataNodesList.size() <= 0) {
			LOGGER.error("The logicTable and actualDataNodes should not be empty，logicTableList.size:{},actualDataNodeList.size:{}",
					logicTableList.size(), actualDataNodesList.size());
			throw new RuntimeException("The logicTable and actualDataNodes should not be empty!");
		}

		List<TableRuleConfiguration> tableRuleConfigurationList = new ArrayList<>();
		for (int i = 0; i < logicTableList.size(); i++) {
			TableRuleConfiguration tableRuleConfiguration = new TableRuleConfiguration(logicTableList.get(i),
					actualDataNodesList.get(i));
			// 这里目前只做标准分片策略下的处理，其他分片策略可以之后进行扩展并自定义实现分片算法即可
			if (shardingStrategysList.get(i).equals(ShardingStrategy.STANDARD.name())) {
				ShardingStrategyConfiguration shardingStrategyConfiguration = new StandardShardingStrategyConfiguration(shardingColumnsList.get(i), new PreciseAndRangShardingAlgorithm(),
						new PreciseAndRangShardingAlgorithm());
				tableRuleConfiguration.setTableShardingStrategyConfig(shardingStrategyConfiguration);
				// 可以通过读取配置中算法实现类的包路径并反射来实现
//				shardingStrategyConfiguration = new StandardShardingStrategyConfiguration(shardingColumnsList.get(i),
//						new ShardingSphereAlgorithm<PreciseShardingAlgorithm>(shardingAlgorithmsList.get(i)).getInstance(),
//						new ShardingSphereAlgorithm<RangeShardingAlgorithm>(shardingAlgorithmsList.get(i)).getInstance());
			}
			tableRuleConfigurationList.add(tableRuleConfiguration);
		}
		return tableRuleConfigurationList;
	}

	/**
	 * 根据类路径获取类实例
	 * @param <T>
	 */
	class ShardingSphereAlgorithm<T> {
		
		private String classPath;
		
		public ShardingSphereAlgorithm(String classPath){
			this.classPath = classPath;
		}
		
		public T getInstance() {
			try {
				Class<?> clazz = Class.forName(classPath);
				return (T) clazz.newInstance();
			} catch (ClassNotFoundException e) {
				LOGGER.error("ShardingSphereConfiguration.getInstance", e.getMessage());
			} catch (InstantiationException e) {
				LOGGER.error("ShardingSphereConfiguration.getInstance", e.getMessage());
			} catch (IllegalAccessException e) {
				LOGGER.error("ShardingSphereConfiguration.getInstance", e.getMessage());
			}
			return null;
		}
		
	}
}
